package com.tencent.wxcloudrun.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.BooleanUtil;
import com.tencent.wxcloudrun.config.ConstantsConfig;
import com.tencent.wxcloudrun.dto.RepaymentInfo;
import com.tencent.wxcloudrun.model.ApplyRecord;
import com.tencent.wxcloudrun.model.Task;
import com.tencent.wxcloudrun.repository.TaskRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import javax.transaction.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class TaskService {

    @Resource
    private TaskRepository taskRepository;

    // 分页查询任务列表，支持任务状态和逾期日期查询
    public Page<Task> getTaskList(Task.TaskStatus status, Pageable pageable) {
        return taskRepository.findAllByStatus(status, pageable);
    }

    public Page<Task> searchTaskRecords(Long userId, Task.TaskStatus status, String phone, String name, LocalDate dateTime, Pageable pageable) {
        return searchTaskRecords(userId, status, phone, name, dateTime, false, pageable);
    }


    public Page<Task> searchTaskRecordsByEndDate(Long userId, Task.TaskStatus status, String phone, String name, LocalDate dateTime, Pageable pageable) {
        return searchTaskRecords(userId, status, phone, name, dateTime, true, pageable);
    }


    /**
     *
     * @param userId
     * @param status
     * @param phone
     * @param name
     * @param dateTime
     * @param searchByEndDate   是否按最后还款时间查询
     * @param pageable
     * @return
     */
    public Page<Task> searchTaskRecords(Long userId, Task.TaskStatus status, String phone, String name, LocalDate dateTime, Boolean searchByEndDate, Pageable pageable) {
        // 创建一个按 createdAt 字段降序排列的 Sort 对象
        Sort sort = Sort.by(Sort.Direction.ASC, "periodEndDate");
        // 创建包含排序规则的 Pageable 对象
        Pageable sortedPageable = PageRequest.of(
                pageable.getPageNumber(),
                pageable.getPageSize(),
                sort
        );
        Specification<Task> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (null != userId) {
                // 使用 criteriaBuilder 构建 equal 条件
                predicates.add(criteriaBuilder.equal(root.get("userId"), userId));
            }
            if (status != null) {
                // 使用 criteriaBuilder 构建 equal 条件
                predicates.add(criteriaBuilder.equal(root.get("status"), status));
            }
            if (phone != null && !phone.isEmpty()) {
                // 使用 criteriaBuilder 构建 like 条件
                predicates.add(criteriaBuilder.like(root.get("phone"), "%" + phone + "%"));
            }
            if (name != null && !name.isEmpty()) {
                // 使用 criteriaBuilder 构建 like 条件
                predicates.add(criteriaBuilder.like(root.get("username"), "%" + name + "%"));
            }

            if (dateTime != null) {
                if (BooleanUtil.isTrue(searchByEndDate)) {
                    predicates.add(criteriaBuilder.equal(root.get("periodEndDate"), dateTime));
                } else {
                    // 将 LocalDateTime 转换为 LocalDate
                    // 添加还款周期的条件判断
                    predicates.add(criteriaBuilder.and(
                            criteriaBuilder.lessThanOrEqualTo(root.get("periodStartDate"), dateTime),
                            criteriaBuilder.greaterThanOrEqualTo(root.get("periodEndDate"), dateTime)
                    ));
                }
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        return taskRepository.findAll(spec, sortedPageable);
    }


    /**
     *
     * @param userId
     * @param phone
     * @param name
     * @param pageable
     * @return
     */
    public Page<Task> searchOverdueTaskRecords(Long userId, String phone, String name, Pageable pageable) {
        // 创建一个按 createdAt 字段降序排列的 Sort 对象
        Sort sort = Sort.by(Sort.Direction.DESC, "periodEndDate");
        // 创建包含排序规则的 Pageable 对象
        Pageable sortedPageable = PageRequest.of(
                pageable.getPageNumber(),
                pageable.getPageSize(),
                sort
        );
        Specification<Task> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (null != userId) {
                // 使用 criteriaBuilder 构建 equal 条件
                predicates.add(criteriaBuilder.equal(root.get("userId"), userId));
            }
            // 使用 criteriaBuilder 构建 notEqual 条件
            predicates.add(criteriaBuilder.notEqual(root.get("status"), Task.TaskStatus.PAID));
            if (phone != null && !phone.isEmpty()) {
                // 使用 criteriaBuilder 构建 like 条件
                predicates.add(criteriaBuilder.like(root.get("phone"), "%" + phone + "%"));
            }
            if (name != null && !name.isEmpty()) {
                // 使用 criteriaBuilder 构建 like 条件
                predicates.add(criteriaBuilder.like(root.get("username"), "%" + name + "%"));
            }
            // 将 LocalDateTime 转换为 LocalDate
            LocalDate currentDate = LocalDate.now();
            // 最后还款日期在今天前
            predicates.add(criteriaBuilder.lessThan(root.get("periodEndDate"), currentDate));
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        return taskRepository.findAll(spec, sortedPageable);
    }


    /**
     * 生成还款计划（按周计算）
     */
    public void generateRepaymentPlan(ApplyRecord applyRecord) {
        Integer weekNum = applyRecord.getWeekNum(); // 还款周期（单位：周）
        Integer limitAmount = applyRecord.getLimitAmount(); // 总金额
        // 获取配置里是否有对应的还款计划
        RepaymentInfo repaymentInfo = ConstantsConfig.getRepaymentInfo(limitAmount, weekNum);
        if (null == repaymentInfo) {
            throw new RuntimeException("未找到该计划，生成日历失败");
        }
        LocalDate firstRepaymentDate = DateUtil.date().toLocalDateTime().toLocalDate(); // 放款当日为第一个周期起点

        double principalPerPeriod = repaymentInfo.getWeeklyPrincipal(); // 每周应还本金
        double interestPerPeriod = repaymentInfo.getInterest(); // 每周利息
        double totalPerPeriod = repaymentInfo.getTotalAmount(); // 每期总还款额

        List<Task> schedules = new ArrayList<>(weekNum);

        for (int i = 1; i <= weekNum; i++) {
            Task schedule = new Task();
            schedule.setApplyRecord(applyRecord);
            schedule.setInstallmentNumber(i);

            LocalDate startDate = firstRepaymentDate.plusWeeks(i - 1); // 计算当前周期的开始日期
            LocalDate endDate = startDate.plusDays(6); // 7天后的结束日期
            schedule.setPeriodStartDate(startDate);
            schedule.setPeriodEndDate(endDate);
            schedule.setUserId(applyRecord.getUser().getId());
            schedule.setUsername(applyRecord.getName());
            schedule.setPhone(applyRecord.getPhone());
            schedule.setTotalWeekNum(applyRecord.getWeekNum());
            schedule.setPrincipal(principalPerPeriod);
            schedule.setInterest(interestPerPeriod);
            schedule.setTotalAmount(totalPerPeriod);
            schedule.setStatus(Task.TaskStatus.UNPAID);
            schedules.add(schedule);
        }
        taskRepository.saveAll(schedules);
    }


    /**
     * 修改任务状态
     * @param taskId 任务id
     * @param status 状态
     * @param actualRepaymentDate 时间
     * @param overdueAmount 逾期金额
     */
    public void updateTaskStatus(Long taskId, Task.TaskStatus status, LocalDate actualRepaymentDate, Double overdueAmount) {
        Task task = taskRepository.findById(taskId).orElseThrow(() -> new RuntimeException("任务不存在"));
        task.setStatus(status);
        if (null != actualRepaymentDate && status == Task.TaskStatus.PAID) {
            task.setActualRepaymentDate(actualRepaymentDate);
        }
        if (null != overdueAmount && status == Task.TaskStatus.OVERDUE) {
            task.setOverdueAmount(overdueAmount);
        }
        task.setUpdatedAt(ZonedDateTime.now(ZoneId.of("Asia/Shanghai")));
        taskRepository.save(task);
    }

    @Transactional
    public void updateTaskStatusByApplyRecordId(Long applyRecordId, Task.TaskStatus newStatus) {
        // 根据 apply_record_id 查询 Task 记录
        List<Task> tasks = taskRepository.findByApplyRecordId(applyRecordId);
        // 遍历查询到的 Task 记录，更新状态
        for (Task task : tasks) {
            task.setStatus(newStatus);
        }
        // 保存更新后的 Task 记录
        taskRepository.saveAll(tasks);
    }

    public void deleteById(Long id) {
        taskRepository.deleteById(id);
    }
}


